/******************************************************************************
 * FILENAME     : DBFM.C
 * PRODUCT     : SoftPay CPAC version
 * VERSION      : 1.0
 * MODULE       : Data Base Module
 * AUTHOR(S)  : Vipin_K1
 * CREATED     : 19-Jul-2000
 *
 * DESCRIPTION : This file contains all functions related to data base file management.
 *
 * NOTES       :
 *
 * CONTENTS    : 
 *
 * MODIFICATION HISTORY    :
 *
 * #  Date       Who        History
 * -- --------   ---------- ---------------------------------------
 *******************************************************************************
 * Copyright (C) 2000 by VeriFone Inc.
 * All rights reserved. No part of this software may be reproduced,transmitted,
 * transcribed, stored in a retrieval system, or translated into any language
 * or computer language, in any form or by any means, electronic, mechanical,
 * magnetic, optical, chemical, manual or otherwise, without the prior written
 * permission of VeriFone Inc.
 *                                                VeriFone Inc.
 *                                                III Lagoon Drive, Suite 400
 *                                                Redwood City, CA 94065
 ******************************************************************************
 */
#include <project.h>
#include <svc.h>
#include <stdio.h>
#include <string.h>
#include <define.h>

#include "dbfm.h"

#define SIZE_UINT   sizeof (unsigned int)

/*---------------------------------------------------------------------------
* Routine Name : inDBCreateFile
* Description  : This function creates the specified DB file with a fixed
*                record size of 'uiRecordSize' in the DB.
*
* Inputs       :
*   pszFileName     - Pointer to the null-terminated file name.
*   uiRecordSize    - Size of the records to be stored in the file.
*
* Outputs      : None
* Returns      :
*       VS_SUCCESS - on success
*       Value < 0 - on failure
*
* Note         :
*       This DB function will store the record size passed in the
*       file it creates. Therefore, it is very important to call the
*       DB related Read & Write functions for proper functioning
*       after this call.
*
*----------------------------------------------------------------------------
*/

int inDBCreateFile(const char* pszFileName,unsigned int uiRecordSize) {
    int inHdl,
    inResult;
    unsigned int uiTotalRecs = 0;

    if ((strlen(pszFileName) == 0) || (uiRecordSize == 0))
        return(DB_INV_INPUT);
    inHdl = open(pszFileName, O_RDWR);
    if (inHdl >= 0) {
        close(inHdl); return(VS_SUCCESS);
    }/* Already created */
    /* Try to Create the file */
    inHdl = open(pszFileName, O_RDWR | O_CREAT);
    if (inHdl < 0)
        return(DB_CREAT_ERR);
    /* The first two bytes indicate the total records */
    inResult = write(inHdl, (const char *) &uiTotalRecs, SIZE_UINT);
    if (inResult != SIZE_UINT) {
        close(inHdl); return(DB_WRITE_ERR);
    }
    /* The next two bytes indicate the record size */
    inResult = write(inHdl, (const char *) &uiRecordSize, SIZE_UINT);
    if (inResult != SIZE_UINT) {
        close(inHdl); return(DB_WRITE_ERR);
    }
    if (close(inHdl) != 0)
        return(DB_CLOSE_ERR);
    return(VS_SUCCESS);
}

/*---------------------------------------------------------------------------
* Routine Name : inReadHeader
* Description  : This function reads the total no.of records and the record
*                size in the DB file specified. This function is private to
*                this module.
*
* Inputs       :
*   inFileHdl       - Handle to the already opened DB file.
*
* Outputs      :
*   puiTotalRecs    - Pointer to the Total Recs in the file
*   puiRecordSize   - Pointer to the size of the records stored in the file.
*
* Returns      :
*       VS_SUCCESS - on success
*       Value < 0 - on failure
*
* Note         :
*----------------------------------------------------------------------------
*/
static int inReadHeader(int inFileHdl,unsigned int* puiTotalRecs,unsigned int* puiRecordSize) {
    if (lseek(inFileHdl, 0L, SEEK_SET) < 0)
        return(DB_SEEK_ERR);
    if (read(inFileHdl, (char *) puiTotalRecs, SIZE_UINT) != SIZE_UINT)
        return(DB_READ_ERR);
    if (read(inFileHdl, (char *) puiRecordSize, SIZE_UINT) != SIZE_UINT)
        return(DB_READ_ERR);
    return(VS_SUCCESS);
}


/*---------------------------------------------------------------------------
* Routine Name : inDBReadRecord
* Description  : This function reads the specified record from the specified
*                DB file and stores the result in the passed buffer.
*
* Inputs       :
*   pszFileName     - Pointer to the null-terminated file name.
*   uiRecNum        - Record number to be read.
*
* Outputs      :
*       pucBuf          - Pointer to the buffer where data read is stored.
*
* Returns      :
*       Value >= 0       - No.of bytes read
*       Value < 0   - on failure
* Note         : The file specified in this call must have been created using
*                inDBCreateFile() prior to calling this function.
*                Record number of the first record is '0'.
*                All records in the files are assumed to start from no. '1'.
*----------------------------------------------------------------------------
*/
int inDBReadRecord(const char* pszFileName,unsigned int uiRecNum,unsigned char* pucBuf) {
    int inHdl,
    inResult;
    unsigned int uiTotalRecs, uiRecordSize;
    long lnOffset,
    lnBytes;

    if ((strlen(pszFileName) == 0) || (pucBuf == 0) || (uiRecNum == 0))
        return(DB_INV_INPUT);
    inHdl = open(pszFileName, O_RDWR);
    if (inHdl < 0)
        return(DB_OPEN_ERR);
    /* Get header info */
    inResult = inReadHeader(inHdl, &uiTotalRecs, &uiRecordSize);
    if (inResult < 0) {
        close(inHdl); return(inResult);
    }
    if (uiTotalRecs == 0) {
        close(inHdl); return(DB_FILE_EMPTY);
    }
    if (uiRecordSize == 0) {
        close(inHdl);return(DB_INV_REC_SIZE);
    }
    if (uiRecNum > uiTotalRecs) {
        close(inHdl); return(DB_REC_NOEXIST);
    }

    lnOffset = (uiRecNum - 1) * uiRecordSize;
    lnBytes = lseek(inHdl, lnOffset, SEEK_CUR);     /* Seek to the record */
    if (lnBytes < 0) {
        close(inHdl); return(DB_SEEK_ERR);
    }

    if (read(inHdl, (char *) pucBuf, uiRecordSize) != uiRecordSize) {
        close(inHdl); return(DB_READ_ERR);
    }
    close(inHdl);
    return((int) uiRecordSize);
}

#if DBFM_REMOVED
/*---------------------------------------------------------------------------
* Routine Name : inDBReadNRecords
* Description  : This function reads 'uiNumOfRecs' records from the specified
*                file, starting from 'uiStartRecNum' and stores the result in
*                'pucBuf'. If the no.of records requested is more than what is
*                available, only maximum possible is read.
*
* Inputs       :
*   pszFileName     - Pointer to the null-terminated file name.
*       uiStartRecNum   - Number of the first record to start reading.
*       uiNumOfRecs     - Number of records to be read.
*
* Outputs      :
*       pucBuf          - Pointer to the buffer where data read is to be
*                         stored.
*
* Returns      :
*       Value >= 0  - No.of records read
*       Value < 0   - on failure
* Note         : The file specified in this call must have been created using
*                inDBCreateFile() prior to calling this function.
*
*                All records in the files are assumed to start from no. '1'.
*----------------------------------------------------------------------------
*/
int inDBReadNRecords(const char* pszFileName,unsigned int uiStartRecNum,unsigned int uiNumOfRecs,unsigned char* pucBuf) {
    int inHdl,
    inResult,
    inBytesRead = 0,
    inRecsAvailable,
    inCount;
    unsigned int uiTotalRecs, uiRecordSize;
    long lnOffset,
    lnBytes;

    if ((strlen(pszFileName) == 0) || (pucBuf == 0) || (uiNumOfRecs == 0) || (uiStartRecNum == 0))
        return(DB_INV_INPUT);
    inHdl = open(pszFileName, O_RDWR);
    if (inHdl < 0)
        return(DB_OPEN_ERR);

    inResult = inReadHeader(inHdl, &uiTotalRecs, &uiRecordSize);
    if (inResult < 0) {
        close(inHdl); return(inResult);
    }
    if (uiTotalRecs == 0) {
        close(inHdl); return(DB_FILE_EMPTY);
    }
    if (uiStartRecNum > uiTotalRecs) {
        close(inHdl); return(DB_INV_INPUT);
    }
    if (uiRecordSize == 0) {
        close(inHdl); return(DB_INV_REC_SIZE);
    }

    lnOffset = (uiStartRecNum - 1) * uiRecordSize;/* Seek to first record */
    lnBytes = lseek(inHdl, lnOffset, SEEK_CUR);
    if (lnBytes < 0) {
        close(inHdl); return(DB_SEEK_ERR);
    }

    inRecsAvailable = uiTotalRecs - uiStartRecNum + 1;
    /* Check if No.of recs requested is more than what is present */
    if (uiNumOfRecs > inRecsAvailable)
        uiNumOfRecs = inRecsAvailable;
    for (inCount = 0; inCount < uiNumOfRecs; inCount++) {
        if (read(inHdl, (const char *) (pucBuf + inBytesRead), uiRecordSize) != uiRecordSize) {
            close(inHdl); return(DB_READ_ERR);
        }
        inBytesRead += uiRecordSize;
    }
    close(inHdl);                 /* PROTON_MALAYSIA 151298 Handle Fixed */
    return((int) uiNumOfRecs);
}

#endif /* DBFM_REMOVED */

/*---------------------------------------------------------------------------
* Routine Name : inDBWriteRecord
* Description  : This function writes a record from the data specified in
*                'pucBuf' in to the specified file at the record number
*                'inRecNum'. If 'inRecNum' is passed the value 'DB_APPENDREC',
*                the record is going to be appended to the file.
*
*
* Inputs       :
*       pszFileName     - Pointer to the null-terminated file name.
*       inRecNum        - Record Number
*       pucBuf          - Pointer to the buffer where data is to be written
*                         from.
*
* Outputs      : None
* Returns      :
*       Value >= 0       - No.of bytes written to the file.
*       Value < 0       - on failure
* Note         : The file specified in this call must have been created using
*                inDBCreateFile() prior to calling this function.
*
*                All records in the files are assumed to start from no. '1'.
*----------------------------------------------------------------------------
*/
int inDBWriteRecord(const char* pszFileName,int inRecNum,const unsigned char* pucBuf) {
    int inHdl,
    inResult;
    unsigned int uiTotalRecs, uiRecordSize;
    long lnOffset,
    lnBytes;
    VS_BOOL fAppend = VS_TRUE;

    if ((strlen(pszFileName) == 0) || (pucBuf == 0) || (inRecNum == 0))
        return(DB_INV_INPUT);
    if ((inRecNum < 0) && (inRecNum != DB_APPENDREC))
        return(DB_INV_INPUT);

    inHdl = open(pszFileName, O_RDWR);
    if (inHdl < 0)
        return(DB_OPEN_ERR);

    inResult = inReadHeader(inHdl, &uiTotalRecs, &uiRecordSize);
    if (inResult < 0) {
        close(inHdl); return(inResult);
    }
    if (uiRecordSize == 0) {
        close(inHdl); return(DB_INV_REC_SIZE);
    }
    if (inRecNum > (int) uiTotalRecs + 1) {
        close(inHdl); return(DB_INV_INPUT);
    }

    if ((inRecNum == DB_APPENDREC) || (inRecNum == (int) uiTotalRecs + 1))
        lnBytes = lseek(inHdl, 0L, SEEK_END);
    else {
        /* Existing record to be overwritten */
        lnOffset = (inRecNum - 1) * uiRecordSize;   /* Seek to the record */
        lnBytes = lseek(inHdl, lnOffset, SEEK_CUR);
        fAppend = VS_FALSE;
    }
    if (lnBytes < 0) {
        close(inHdl); return(DB_SEEK_ERR);
    }

    inResult = write(inHdl, (const char *) pucBuf, uiRecordSize);    /* Write the record */
    if (inResult != uiRecordSize) {
        close(inHdl); return(DB_WRITE_ERR);
    }
    if (fAppend == VS_TRUE) {
        uiTotalRecs++;                              /* Successful write   */
        lnBytes = lseek(inHdl, 0L, SEEK_SET);       /* Update header info */
        if (write(inHdl, (const char *) &uiTotalRecs, SIZE_UINT) != SIZE_UINT) {
            close(inHdl); return(DB_WRITE_ERR);
        }
    }
    close(inHdl);
    return(inResult);
}


/*---------------------------------------------------------------------------
* Routine Name : inDBDeleteRecord
* Description  : This function deletes the record number 'uiRecNum' from the
*                specified file.
*
* Inputs       :
*   pszFileName     - Pointer to the null-terminated file name.
*       uiRecNum        - Record Number to be deleted.
*
* Outputs      : None
* Returns      :
*       VS_SUCCESS      - on successful delete
*       Value < 0       - on failure
* Note         : The file specified in this call must have been created using
*                inDBCreateFile() prior to calling this function.
*
*                All records in the files are assumed to start from no. '1'.
*----------------------------------------------------------------------------
*/
int inDBDeleteRecord(const char* pszFileName,unsigned int uiRecNum) {
    int inHdl,
    inResult;
    unsigned int uiTotalRecs, uiRecordSize;
    long lnOffset,
    lnBytes;

    if ((strlen(pszFileName) == 0) || (uiRecNum == 0))
        return(DB_INV_INPUT);

    inHdl = open(pszFileName, O_RDWR);
    if (inHdl < 0)
        return(DB_OPEN_ERR);

    inResult = inReadHeader(inHdl, &uiTotalRecs, &uiRecordSize);
    if (inResult < 0) {
        close(inHdl); return(inResult);
    }
    if (uiRecordSize == 0) {
        close(inHdl); return(DB_INV_REC_SIZE);
    }
    if (uiTotalRecs == 0 || uiRecNum > uiTotalRecs) {
        close(inHdl); return(DB_REC_NOEXIST);
    }

    lnOffset = (uiRecNum - 1) * uiRecordSize;      /* Seek to the record */
    lnBytes = lseek(inHdl, lnOffset, SEEK_CUR);
    if (lnBytes < 0) {
        close(inHdl); return(DB_SEEK_ERR);
    }

    inResult = delete(inHdl, uiRecordSize);         /* Delete the record */
    if (inResult < 0) {
        close(inHdl); return(inResult);
    }
    /* Successful delete  */
    uiTotalRecs--;
    lnBytes = lseek(inHdl, 0L, SEEK_SET);
    /* Update header info */
    if (write(inHdl, (const char *) &uiTotalRecs, SIZE_UINT) != SIZE_UINT) {
        close(inHdl); return(DB_WRITE_ERR);
    }
    close(inHdl);
    return(VS_SUCCESS);
}


/*---------------------------------------------------------------------------
* Routine Name : inDBFileExists
* Description  : This function checks for the existence of the specified file
*                in the DB.
*
* Inputs       :
*   pszFileName     - Pointer to the null-terminated file name.
*
* Outputs      : None
* Returns      :
*       VS_SUCCESS      - On successful removal
*       VS_FAILURE      - on failure
*       DB_INV_INPUT - Invalid parameter
* Note         :
*----------------------------------------------------------------------------
*/
int inDBFileExists(const char* pszFileName) {
    int inHdl;

    if (strlen(pszFileName) == 0)
        return(DB_INV_INPUT);
    inHdl = open(pszFileName, O_RDWR);
    if (inHdl < 0)
        return(VS_ERROR);
    close(inHdl);
    return(VS_SUCCESS);
}

/*---------------------------------------------------------------------------
* Routine Name : inDBRemoveFile
* Description  : This function removes the specified file from the DB.
*
* Inputs       :
*   pszFileName     - Pointer to the null-terminated file name.
*
* Outputs      : None
* Returns      :
*       VS_SUCCESS      - On successful removal
*       DB_INV_INPUT    - Invalid parameter
*       VS_FAILURE      - on failure
* Note         :
*----------------------------------------------------------------------------
*/
int inDBRemoveFile(const char* pszFileName) {
    int inResult;

    if (strlen(pszFileName) == 0)
        return(DB_INV_INPUT);
    inResult = remove(pszFileName);
    if (inResult < 0)
        return(VS_ERROR);
    return(VS_SUCCESS);
}


/*---------------------------------------------------------------------------
* Routine Name : inDBTotalRecords
* Description  : This function returns the total number of records present in
*                the specified file.
*
* Inputs       :
*   pszFileName     - Pointer to the null-terminated file name.
*
* Outputs      : None
* Returns      :
*       Value >= 0       - Total no.of records
*       Value < 0       - on failure
* Note         : The file specified in this call must have been created using
*                inDBCreateFile() prior to calling this function.
*
*----------------------------------------------------------------------------
*/
int inDBTotalRecords(const char* pszFileName) {
    int inHdl;
    unsigned int uiTotalRecs;

    if (strlen(pszFileName) == 0)
        return(DB_INV_INPUT);
    inHdl = open(pszFileName, O_RDWR);
    if (inHdl < 0)
        return(DB_OPEN_ERR);
    if (read(inHdl, (char *) &uiTotalRecs, SIZE_UINT) != SIZE_UINT) {
        close(inHdl); return(DB_READ_ERR);
    }
    close(inHdl);
    return((int) uiTotalRecs);
}





